/* 
 * File:   PJLinkV1.cpp
 * Author: longtran
 * 
 * Created on March 20, 2011, 2:10 AM
 */

#include "pjlinkv1.h"


#include <QtCore/QCryptographicHash>
#include <QtNetwork/QTcpSocket>
#include <QtCore/QStringList>


namespace Projector
{

const QString PJLinkV1::sHeaderPrefix("%");
const QString PJLinkV1::sClassNumber("1");
const QString PJLinkV1::sInputCmd("INPT");
const QString PJLinkV1::sPowerCmd("POWR");
const QString PJLinkV1::sPJLink("PJLINK");

const int PJLinkV1::sPJLinkPort(4352);


PJLinkV1::PJLinkV1()
{
    mInputs = QMap<QString, PJLinkV1Code*>();
    mInputResponse = QMap<QString, PJLinkV1Code*>();
    mPowerStates = QMap<QString, PJLinkV1Code*>();
    mPowerStateResponse = QMap<QString, PJLinkV1Code*>();

}

PJLinkV1::~PJLinkV1() {

    qDeleteAll(mInputs);
    qDeleteAll(mInputResponse);
    qDeleteAll(mPowerStates);
    qDeleteAll(mPowerStateResponse);

}

PJLinkV1Code const* PJLinkV1::FindInput(const QString& input) const
{
    return mInputs.value(input);
}

PJLinkV1Code const* PJLinkV1::FindPowerStatus(const QString& powerState) const
{
    return mPowerStates.value(powerState);
}

PJLinkV1Code const* PJLinkV1::FindInputResponse(const QString& response) const
{
    return mInputResponse.value(response);
}

PJLinkV1Code const* PJLinkV1::FindPowerStateResponse(const QString& response) const
{
    return mPowerStateResponse.value(response);
}


bool PJLinkV1::TurnOn(const bool hasPassword, const QString& password, const QHostAddress& address) const
{

    QString digest("");
    QTcpSocket socket;

    socket.connectToHost(address, 4352, QIODevice::ReadWrite);
    QByteArray data = socket.readLine();
    QString stringData(data);

    QStringList tokens = stringData.split(" ");

    if(tokens.at(INFOMESSAGE_Protocol).compare(PJLinkV1::sPJLink) != 0)
    {
#ifdef DEBUG
        qDebug() << "NOT PJLINK Protocol";
#endif
        // TODO error message dialog
        return false;
    }

    if(tokens.at(INFOMESSAGE_Security).compare("1") == 0)
    {
        digest = CreatePasswordDigest(password, tokens.at(INFOMESSAGE_RandomNumber));
    }

    // write the command
    QString cmd = digest + CreateQuery( sPowerCmd, QString(mPowerStateResponse.value(QString("on"))->GetCode())) + QString('\r');

    // send to projector
    socket.write(cmd.toAscii());

    // get projector response
    QByteArray response = socket.readLine();

    // check for any errors
    QStringList responseTokens = QString(response).split('=');

    if( responseTokens.at(RESPONSEMESSAGE_Code).compare("OK") == 0)
    {
        return true;
    }

    return true;
}

bool PJLinkV1::TurnOff(const bool hasPassword, const QHostAddress& address) const
{
    CreateQuery( sPowerCmd, QString(mPowerStateResponse.value(QString("off"))->GetCode()));
    return true;
}

bool PJLinkV1::SwitchInput(const QString& name) const
{
    // TODO: Complete this function
    return true;
}

bool PJLinkV1::BlackScreen() const
{
    // TODO: Complete this function
    return true;
}

QString PJLinkV1::CreateQuery(const QString& command, const QString& parameter)
{
    QString query = QString();

    query = query + sHeaderPrefix + sClassNumber + command + QString(" ") + parameter + QString('\r');

#ifdef DEBUG

    qDebug() << query;

#endif

    return query;
}

QString PJLinkV1::CreatePasswordDigest(const QString& password, const QString& randomNumber)
{

    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(randomNumber.toAscii(), randomNumber.size());
    hash.addData(password.toAscii(), password.size());
    QString digest(hash.result().toHex());

    return digest;
}



}
